package com.example.permissionservice.service;

import com.example.permissionservice.config.RedisManager;
import com.myprojects.common.pojo.UserWithRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.*;

@Service
public class UserTokenService {
    //默认过期时间为60s
    private static final long DEFAULT_EXPIRE_TIME = 1 * 24 * 60 * 60;

    @Autowired
    RedisManager redisManager;

    private final static String USESR_TOKEN_HASH_NAME = "userToken";

    /**
     * 用于根据准确的键来获取用户对象
     * @param token 准确的键名
     */
    public UserWithRole getUserByAccurateToken(String token){
        return (UserWithRole)redisManager.getObject(token);
    }

    /**
     * 用于根据键来获取符合结果的键-值对，支持通配符模糊搜索
     * @param searchString 用来搜索的键，不能为null
     * @return 返回 HashMap<String, User> 类型的结果集，<br/>
     * 当 map.size() = 0 时说明没有任何搜索结果
     */
    public HashMap<String, UserWithRole> searchUserByString(String searchString){
        HashMap<String,UserWithRole> userMap = new HashMap();
        if (searchString == null)
            return userMap;

        HashMap<String,Object> objectMap = redisManager.scanByPattern(searchString);

        for (Map.Entry<String,Object> entry : objectMap.entrySet()){
            try{
                userMap.put(entry.getKey(), (UserWithRole) entry.getValue());
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        return userMap;
    }

    /**
     * 用于设置用户token
     *
     * @param user 需要设置token的用户对象
     * @return 返回 String 为该用户的token,返回null则为设置失败
     */
    public String setUserToken(UserWithRole user){
        //添加之前必须先删除该用户
        deleteUserById(user.getId());
        String uuidStr = UUID.randomUUID().toString();
        String md5Str = DigestUtils.md5DigestAsHex(uuidStr.getBytes());
        String itemKey = md5Str+"{id:"+user.getId()+"}";
        boolean setKeyResult = redisManager.setObject(itemKey, user, DEFAULT_EXPIRE_TIME);
//        if (setKeyResult){
//            //设置过期时间
//            redisManager.expire(itemKey, DEFAULT_EXPIRE_TIME);
//        }
        return setKeyResult ? md5Str : null;
    }

    /**
     * 用于更新用户token的值的用户信息，全部都同时更新
     *
     * @param user 需要被更新的用户对象
     * @return 返回 boolean 值，true为成功，false为失败
     */
    public boolean updateTokenUser(UserWithRole user){
        user.setPassword(null);
        user.setEncrypt_password(null);
        HashMap<String, UserWithRole> hashMap = searchUserByString("*{id:"+user.getId()+"}*");
        String userKey = null;
        for (String value : hashMap.keySet()) {
            userKey = value;
            break;
        }
        boolean result = redisManager.setObject(userKey, user, DEFAULT_EXPIRE_TIME);

        return result;
    }

    /**
     * 用于模糊搜索键的前半部分并删除全部符合结果的键
     * @param tokenStr 为用于模糊搜索用的字符串，<br/>
     *                 它的后半部分会拼接上"*"，不能为null，如为null则转为"null"
     * @return 返回 boolean 值，<br/>
     * true为有搜索结果并可能删除成功，false为没有搜索结果
     */
    public boolean deleteUserByTokenString(String tokenStr){
        tokenStr = (tokenStr == null) ? "null" : tokenStr;
        // 替换掉所有通配符，以免发生注入
        tokenStr = tokenStr.replaceAll("[*?\\[\\]]","");
        if (tokenStr.length() < 32 ||
                "".equals(tokenStr.trim())){
            tokenStr = "null";
        }
//        System.out.println("tokenStr:"+tokenStr);

        HashMap<String, UserWithRole> hashMap = this.searchUserByString(tokenStr+"*");
        if (hashMap.size()>0){
            List<String> keyList = new ArrayList<>();
            for (String value : hashMap.keySet()) {
//                System.out.println("value = " + value);
                keyList.add(value);
            }
            redisManager.deleteKey(keyList.toArray(new String[]{}));
            return true;
        }else {
            return false;
        }
    }

    /**
     * 用于根据id并删除全部符合结果的键
     * @param ids 为用于模糊搜索用的字符串
     * @return 返回 boolean 值，<br/>
     * true为有搜索结果并可能删除成功，false为没有搜索结果
     */
    public boolean deleteUserById(Integer... ids){
        List<String> keyList = new ArrayList<>();
        for ( Integer id : ids){
            HashMap<String, UserWithRole> hashMap = this.searchUserByString("*{id:"+id+"}*");
            for (String value : hashMap.keySet()) {
                keyList.add(value);
            }
        }

        if (keyList.size()>0){
//            redisManager.hashDelete(USESR_TOKEN_HASH_NAME,keyList.toArray(new String[]{}));
            redisManager.deleteKey(keyList.toArray(new String[]{}));
            return true;
        }else {
            return false;
        }
    }


}
